package com.tools.common.object.json.deserializer;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.tools.common.exception.DataGenerationException;
import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 类型包装类的反序列化处理器
 * */
@Note("类型包装类的反序列化处理器")
public class TypeClassHandler {

    private TypeClassHandler() {}


    @Note("Class 类的反序列化")
    public static StdDeserializer<Class> classDeserializer() {
        return new StdDeserializer<Class>(Class.class) {
            @Override
            public Class deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String classname = jsonParser.getText();
                try {
                    return Class.forName(classname);
                } catch (Exception e) {
                    throw new DataGenerationException(classname + " 不能转换为 java.lang.Class 类");
                }
            }
        };
    }


    @Note("类型包装类实例的反序列化")
    public static StdDeserializer<C> cStdDeserializer() {
        return new StdDeserializer<C>(C.class) {
            @Override
            public C deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                return private_newC(jsonParser);
            }
        };
    }



    /* *******************************************************************************************
     *
     *          私有逻辑
     *
     * *******************************************************************************************
     * */


    @Note("创建新的 C 包装类对象")
    private static C private_newC(JsonParser jsonParser) throws IOException {
        String mainTypeClassname = null;
        String dateFormatPattern = null;
        C<?>[] genericTypes = null;
        List<C.TV> argNameAndValues = null;
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String fieldName = jsonParser.getCurrentName();
            if("mainType".equals(fieldName)) {
                mainTypeClassname = jsonParser.getValueAsString();
                continue;
            }
            if("dateFormatPattern".equals(fieldName)) {
                dateFormatPattern = jsonParser.getValueAsString();
                continue;
            }
            if("genericTypes".equals(fieldName)) {
                genericTypes = private_getGenericTypes(jsonParser);
                continue;
            }
            if("argNameAndValues".equals(fieldName)) {
                argNameAndValues = private_getTypeAndValueList(jsonParser);
            }
        }
        Class<?> mainType = ObjKit.getObjectClass(mainTypeClassname);
        C c = C.getC(mainType);
        Class<C> cClass = C.class;
        ObjKit.setFieldValue(cClass, c, "mainType", mainType);
        ObjKit.setFieldValue(cClass, c, "dateFormatPattern", dateFormatPattern);
        ObjKit.setFieldValue(cClass, c, "genericTypes", genericTypes);
        ObjKit.setFieldValue(cClass, c, "argNameAndValues", argNameAndValues);
        return c;
    }

    @Note("如果 value 是字符串类型，那就直接获取")
    private static String private_getStringValue(JsonParser jsonParser) throws IOException {
        jsonParser.nextToken();
        return jsonParser.getText();
    }

    @Note("处理并获取泛型数组")
    private static C<?>[] private_getGenericTypes(JsonParser jsonParser) throws IOException {
        jsonParser.nextToken();
        if (jsonParser.currentToken() == JsonToken.START_ARRAY) {
            List<C> genericTypeList = new ArrayList<>();
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                C c = private_newC(jsonParser);
                genericTypeList.add(c);
            }
            C<?>[] genericTypes = new C<?>[genericTypeList.size()];
            for (int i = 0; i < genericTypeList.size(); i++) {
                genericTypes[i] = genericTypeList.get(i);
            }
            return genericTypes;
        }
        return null;
    }

    @Note("得到 C 包装的类的构造器的形参列表")
    private static List<C.TV> private_getTypeAndValueList(JsonParser jsonParser) throws IOException {
        jsonParser.nextToken();
        if (jsonParser.currentToken() == JsonToken.START_ARRAY) {
            List<C.TV> argNameAndValues = new ArrayList<>();
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                Class<?> type = null;
                Object value = null;
                while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                    String fieldName = jsonParser.getCurrentName();
                    if("type".equals(fieldName)) {
                        jsonParser.nextToken();
                        String classname = jsonParser.getValueAsString();
                        type = ObjKit.getObjectClass(classname);
                        continue;
                    }
                    if("value".equals(fieldName)) {
                        jsonParser.nextToken();
                        String stringJson = jsonParser.getText();
                        value = ObjKit.stringToRealValue(stringJson, C.getC(type));
                    }
                    C.TV tv = new C.TV(type, value);
                    argNameAndValues.add(tv);
                }
            }
            return argNameAndValues;
        }
        return null;
    }
}
